package com.tian.excel.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tian.excel.entity.Permission;
import com.tian.excel.entity.User;
import com.tian.excel.mapper.PermissionMapper;
import com.tian.excel.mapper.UserMapper;
import org.redisson.api.RBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author: Tian
 * @version: 1.0
 * @since: 1.0
 * @date: 2024/7/29/14:39
 */
@Service
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Autowired
   private PermissionMapper permissionMapper;
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RBloomFilter bloomFilter;




    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        HashOperations ho = redisTemplate.opsForHash();
        if((redisTemplate.hasKey("user"+username))) {
            if(ho.hasKey("user"+username,"null")) {
                return new org.springframework.security.core.userdetails.User(null, null, null);
            }
            Map user = ho.entries("user"+username);
            User user1 = BeanUtil.mapToBean(user,User.class,true);
            return userDetails(user1);
        }
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", username);
        User user = userMapper.selectOne(userQueryWrapper);
        if(Objects.nonNull(user)){
            Map<String, Object> map = BeanUtil.beanToMap(user);
            ho.putAll("user"+username,map);
            bloomFilter.add(user.getUsername());
        }else {
            ho.put("user"+username,"null","null");
            redisTemplate.expire("user"+username,5, TimeUnit.SECONDS);
            return new org.springframework.security.core.userdetails.User(null, null, null);
        }
        return userDetails(user);
    }


    public UserDetails userDetails(User user) {
        ValueOperations vo = redisTemplate.opsForValue();
        String key="security"+user.getUsername();
        Object o = vo.get(key);
        if(Objects.nonNull(o)) {
            List<?> c = Convert.toList(o);
            List<SimpleGrantedAuthority> c1 = c.stream().map(item -> new SimpleGrantedAuthority((String) item)).collect(Collectors.toList());
            return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getUserpwd(), c1);
        }

        String nullObject = (String) vo.get(key + "NullObject");
        if(Objects.nonNull(nullObject)) {
                if (nullObject.equals("null")) {
                    return new org.springframework.security.core.userdetails.User(null, null, null);
                }
        }

        //查询当前用户具有的权限
        List<Permission> permissions = permissionMapper.selectByUserId(user.getUserid());
        List<SimpleGrantedAuthority> collect=new ArrayList<>();
        if(permissions.size()>0) {
            collect= permissions.stream().map(item -> new SimpleGrantedAuthority(item.getPercode())).collect(Collectors.toList());
            String s = Convert.toStr(collect);
            vo.set(key, s);
        }else {
            vo.set(key+"NullObject","null",5, TimeUnit.SECONDS);
        }
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getUserpwd(), collect);
    }

}
